#include "ServiceManager.h"


std::unique_ptr<ServiceManager> ServiceManager::instance;
std::mutex ServiceManager::singleton_mutex;

ServiceManager& ServiceManager::getInstance(){
    if (!ServiceManager::instance){
        std::lock_guard<std::mutex> lock(ServiceManager::singleton_mutex);
        if (!ServiceManager::instance){
            instance.reset(new ServiceManager());
        }
    }
    return *instance;
}

ServiceManager::ServiceManager()
{
    // std::thread([this]() {
    //     while (true) {
    //         syncServices();
    //         std::this_thread::sleep_for(std::chrono::seconds(1));
    //     }
    // }).detach();
}

ServiceItem ServiceManager::getNextService(std::string name)
{
    return strategy->Select(name, services_map[name].getServiceList());
}

void ServiceManager::syncServices()
{
    auto services = agent->services();
    for (const auto& svc : services) {
        std::cout << "Discovered service: "<<svc.first<<std::endl;
        ServiceInfo service_info = svc.second;
        std::cout << "Service Address: " << service_info.address 
                << " Service Name: " << service_info.name
                << " Service Port: " << service_info.port
                << " Service ID: " << service_info.id
                << " Service Tags: ";
        for (const auto& tag : service_info.tags) {
            std::cout << tag << " ";
        }
        std::cout<<std::endl;
    }
}

void ServiceManager::syncService(std::string service_name)
{
    ppconsul::health::Health health(*consul_client);  
    auto instances = health.service(service_name);
    for (const auto& instance : instances) {
        const auto& node = std::get<0>(instance);       // Node 信息（包含 IP）
        const auto& service_info = std::get<1>(instance);  // ServiceInfo（包含端口、ID）
        const auto& checks = std::get<2>(instance);     // 健康检查信息

        std::cout << "Service Name: " << service_info.name << std::endl;
        std::cout << "Node Address (IP): " << node.address << std::endl;
        std::cout << "Service Port: " << service_info.port << std::endl;
        std::cout << "Service ID: " << service_info.id << std::endl;
        
    }
}
void ServiceManager::removeServiceInstance(std::string name, ServiceItem service)
{
    services_map[name].removeService(service);
}

void ServiceManager::setConsulConfig(std::string address, std::string token)
{
    this->consul_server_host = address;
    this->consul_token = token;
    this->consul_client = std::make_shared<Consul>(consul_server_host);
    //if (token.empty()) this->consul_client = std::make_shared<Consul>(consul_server_host);
    //else this->consul_client = std::make_shared<Consul>(consul_server_host, consul_token);
    this->agent = std::make_shared<agent::Agent>(*consul_client);
}

void ServiceManager::addServiceInstance(std::string name, ServiceItem service, int ttl_time)
{ 
    services_map[name].addService(service);
    agent->registerService(
        agent::kw::name = service.getName(), 
        agent::kw::port = service.getPort(), 
        agent::kw::address = service.getIp(),
        agent::kw::tags = { "http", "production" },    
        agent::kw::check = agent::TtlCheck(std::chrono::seconds(ttl_time))  
    );
    std::thread t = std::thread([&](){
        while(true){
            // 发送心跳
            std::string service_id = "service:" + service.getName();
            agent->pass(service_id);
            std::this_thread::sleep_for(std::chrono::seconds(10));
        }
    });

    t.detach();
}

void ServiceManager::setLoadBalanceStrategy(const std::shared_ptr<LoadBalanceStrategy>& strategy)
{
    this->strategy = strategy;
}